/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package miselania.memoria_intermedia;

import java.util.LinkedList;
import java.util.Queue;

/**
 *
 * Representa una abstracción de un Gestor de la Memoria Intermedia
 * @author Christian
 */
public class CGestorMemoriaIntermedia 
{
   /** Representa a los bloques de la memoria intermedia o buffer. */
   private CPagina[] buffer;
   /** Numero de paginas en total en el buffer. */
   private int numeroPaginas;
   /** Posición en el buffer de la ultima pagina colocada. */
   private int posicionUltimaPagina = -1;
   /** cola para el control de sustitución basada en LRU. */
   private Queue colaLRU;
   
   public CGestorMemoriaIntermedia(int numeroPaginas)
   {
       this.numeroPaginas=numeroPaginas;
       buffer=new CPagina[numeroPaginas];
       colaLRU = new LinkedList<Integer>();
   }
   
   public CPagina recuperarPaginaDelBuffer(int numeroPagina) 
   {
       // Verificar si la pagina esta en el buffer
       int posicion = posicionDePaginaEnBuffer(numeroPagina);
       if (posicion >= 0) // la pagina esta en el buffer
       {
           // Marcar Pagina o bloque como recientemente referenciado
           colaLRU.remove(numeroPagina);
           colaLRU.add(numeroPagina);
           // devolver la pagina del buffer al solicitante
           return buffer[posicion];
       }
       return null;
   }
   
   /**
     * Poner una pagina en el buffer de la memoria intermedia.
     * 
     * @param pagina la pagina a ser insertado en el buffer.
     * @return la pagina que sera descartada del buffer si es necesario.
     */
    public CPagina ponerPaginaEnBuffer(CPagina pagina) {
       // si la pagina esta en el buffer
       if (estaPaginaEnBuffer(pagina)){
           //no descartar ninguna pagina o bloque
           return null;
       }//si la pagina no esta en el buffer, pero con espacio
       else if (!bufferLleno()) {
           //asignar la nueva pagina al bloque o pagina libre
           posicionUltimaPagina++;
           buffer[posicionUltimaPagina]=pagina;
           //actualizar la LRU
           colaLRU.remove(posicionUltimaPagina);
           colaLRU.add(posicionUltimaPagina);
           return null;
       }// si la pagina no esta en el buffer, pero sin espacio
       else{
           //recuperar la pagina a descartar
           //identificar el id de la pagina a descartar de la cola LRU
           int NumeroPaginaDescartada = (Integer)
                   colaLRU.remove();
           //conociendo el id de pagina ubicar la pposicion de la pagina en el buffer
           int posicion = posicionDePaginaEnBuffer(NumeroPaginaDescartada);
           //extraer la pagina adescartar del buffer
           CPagina paginaDescartada = buffer[posicion];
           //actualizar la nueva pagina en la posicion de la pagina decartada
           buffer[posicion] = pagina;
           //hacer que el id de la nueva pagina sea el mas recientemente referenciado
           colaLRU.add(pagina.getNumeroPagina());
           
           return paginaDescartada;
       }
   }
   private int posicionDePaginaEnBuffer(int numeroPagina) {
       int posicion = -1;
       for (int i=0;i<buffer.length;i++){
           if ((buffer[i] !=null) && (numeroPagina == buffer[i].getNumeroPagina())) {
               posicion = 1;
               break;
           }
       }
       return posicion;
   }
   
   private boolean estaPaginaEnBuffer(CPagina pagina) {
       return (posicionDePaginaEnBuffer(pagina.getNumeroPagina()) !=-1);
   }
   
   private boolean bufferLleno() {
       return numeroPaginas - 1 ==posicionUltimaPagina;
   }
   @Override        
   public String toString() {
       String resultado = "";
       for (int i=0;i<buffer.length;i++) {
           resultado += "Pagina[" + i + "]:" + buffer[i] + "\n";
       }
       return resultado + "\n" + this.colaLRU;
   }
   
   public static void main(String[] args) {
        // Crear un gestor de memoria
        CGestorMemoriaIntermedia gestorBuffer = new CGestorMemoriaIntermedia(6);
        // Paginas del Disco
        System.out.println("Paginas del Disco: ");
        CPagina[] paginas = new CPagina[10];
        for (int i = 0; i < paginas.length; i++) {
            CPagina pagina = new CPagina(i, "p" + i);
            paginas[i] = pagina;
            System.out.println(pagina);
        }

        System.out.println("Contenido del Gestor: ");
        System.out.println(gestorBuffer);


        for (int i = 0; i < paginas.length; i++) {
            gestorBuffer.ponerPaginaEnBuffer(paginas[i]);
        }

        System.out.println("Contenido del Gestor despues de poner bloques: ");
        System.out.println(gestorBuffer);

        System.out.println("Poner una página al Buffer: ");
        CPagina paginaN = new CPagina(10,"p10");
        CPagina paginaE = gestorBuffer.ponerPaginaEnBuffer(paginaN);
        System.out.println(paginaE);
        System.out.println(gestorBuffer);
        
        
        
        System.out.println("Recuperar una Pagina del Buffer: ");
        CPagina pagina1 = gestorBuffer.recuperarPaginaDelBuffer(7);
        System.out.println(pagina1);
        System.out.println(gestorBuffer);

        System.out.println("Recuperar otra Pagina del Buffer: ");
        CPagina pagina2 = gestorBuffer.recuperarPaginaDelBuffer(1);
        System.out.println(pagina2);
        System.out.println(gestorBuffer);
    }
   
   
   
       
}
